package com.jiang.annotation.valid.custom;

import org.apache.commons.lang3.StringUtils;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.util.Arrays;

import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * @author jiangzhe
 *
 * @apiNote
 * 自定义枚举类注解，用于枚举类型值的校验
 * message 可以不写，默认汇集所有枚举值的toString()，提示 "必须为指定值：[xx,xx,...]"
 *
 * {@code
 * @EnumValueCheck(enumClass = IntegerTypeEnum.class, message="the values must in [1, 2]")
 * private int grade;
 * }
 */
@Target({FIELD, PARAMETER})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {EnumValueCheck.EnumValuesValidator.class})
public @interface EnumValueCheck {

    String message() default "";

    Class<? extends Enum<?>> enumClass();

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    class EnumValuesValidator implements ConstraintValidator<EnumValueCheck, Object> {
        private Class clazz;
        private String message;

        @Override
        public void initialize(EnumValueCheck constraintAnnotation) {
            clazz = constraintAnnotation.enumClass();
            message = constraintAnnotation.message();
        }

        @Override
        public boolean isValid(Object value, ConstraintValidatorContext context) {
            if(clazz.isEnum()){
                Enum[] enumValues = (Enum[]) clazz.getEnumConstants();
                if(value instanceof String){
                    for (Enum enumValue: enumValues){
                        if(enumValue.toString().equals(value)){
                            return true;
                        }
                    }
                }
                if(value instanceof Integer){
                    for (Enum enumValue: enumValues){
                        if(enumValue.toString().equals(String.valueOf(value))){
                            return true;
                        }
                    }
                }
                if(StringUtils.isEmpty(message)){
                    context.disableDefaultConstraintViolation();
                    context.buildConstraintViolationWithTemplate("必须为指定值：" + Arrays.asList(enumValues)).addConstraintViolation();
                }
            }
            return false;
        }
    }
}
